Skip to content

Fix TilemapGPULayer when spacing != margin#7339

Open
moufmouf wants to merge 1 commit into
phaserjs:masterfrom
moufmouf:fix/tilemapgpulayer-margin-spacing-stride
Open

Fix TilemapGPULayer when spacing != margin#7339
moufmouf wants to merge 1 commit into
phaserjs:masterfrom
moufmouf:fix/tilemapgpulayer-margin-spacing-stride

Conversation

@moufmouf

Copy link
Copy Markdown
Contributor

This PR (delete as applicable)

  • Fixes a bug

The bug

TilemapGPULayer.vert computes the per-tile stride as tileSize + margin instead of
tileSize + spacing:

outTileStride = uTileWidthHeightMarginSpacing.xy + uTileWidthHeightMarginSpacing.zz;

SubmitterTilemapGPULayer packs that uniform as
(tileWidth, tileHeight, tileMargin, tileSpacing), so .z is margin and .w is
spacing.

The stride from one tile to the next in a tileset image is tileSize + spacing.
Margin is only the one-off border around the whole sheet, and getFrameCorner()
already adds it separately (TilemapGPULayer.frag, where the .zz is correct). So
margin was counted twice — once as the border and again on every step — while spacing
was never counted at all.

The sampled frame therefore drifts by (spacing - margin) * index: exact at index 0
and progressively wrong further down the sheet, eventually sampling entirely unrelated
tiles. Tilesets where margin == spacing are unaffected, which is why this went
unnoticed.

The CPU path is correct, so canvas and WebGL disagree on the same map —
Tileset.updateTileData() strides by tileWidth + tileSpacing from an origin of
tileMargin.

The fix

outTileStride = uTileWidthHeightMarginSpacing.xy + uTileWidthHeightMarginSpacing.ww;

Verification

A new example covering margin != spacing, since no existing one does: phaserjs/examples#410

Before the fix:

image

After the fix:

image

The stride between tiles in a tileset image is tileSize + spacing, but the
shader used tileSize + margin (.zz instead of .ww). Margin is the one-off
border around the sheet and is already added by getFrameCorner(), so it was
counted twice while spacing was never counted at all.

On any tileset where margin != spacing the sampled frame drifts by
(spacing - margin) * index: correct at index 0 and progressively wrong further
down the sheet, eventually rendering unrelated tiles. This matches the CPU path
in Tileset.updateTileData, which strides by tileWidth + tileSpacing from an
origin of tileMargin.

Regenerates the bundled vert shader.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant